# -*- coding: utf-8 -*-
__author__ = 'lztkdr'
__date__ = '2020/4/13 22:10'

"""

归一化和标准化本质上都是一种线性变换。线性变换保持线性组合与线性关系式不变，这保证了特定模型不会失效。

归一化和标准化的区别：

	归一化和标准化的本质都是缩放和平移，他们的区别直观的说就是归一化的缩放是 “拍扁” 统一到区间（0-1），
	而标准化的缩放是更加 “弹性” 和 “动态” 的，和整体样本的分布有很大的关系。

	常见的归一化方法：xi-min(xi)/(max(xi)-min(xi))
	常见的标准化方法：xi-mean(xi)/sd(xi)

	从输出范围角度来看， 归一化的输出结果必须在 0-1 间。而标准化的输出范围不受限制，通常情况下比归一化更广。

	标准化与归一化(缩放到指定范围)的应用场景：

	一般情况下，如果对输出结果范围有要求，用归一化。如果数据较为稳定，不存在极端的最大最小值，用归一化。

	如果数据存在异常值和较多噪音，用标准化，可以间接通过中心化避免异常值和极端值的影响。
	在已有样本足够多的情况下比较稳定，适合现代嘈杂大数据场景,用标准化。


	在机器学习中，标准化是更常用的手段，归一化的应用场景是有限的。其原因就在于二者的区别：

	1、标准化更好保持了样本间距。当样本中有异常点时，归一化有可能将正常的样本“挤”到一起去。
		比如三个样本，某个特征的值为1,2,10000，假设10000这个值是异常值，用归一化的方法后，正常的1,2就会被“挤”到一起去。
		如果不幸的是1和2的分类标签还是相反的，那么，当我们用梯度下降来做分类模型训练时，模型会需要更长的时间收敛，因为将样本分开需要更大的努力！
		而标准化在这方面就做得很好，至少它不会将样本“挤到一起”。

	2、标准化更符合统计学假。对一个数值特征来说，很大可能它是服从正态分布的。
		标准化其实是基于这个隐含假设，只不过是略施小技，将这个正态分布调整为均值为0，方差为1的标准正态分布而已。
"""

"""
数值型的数据：
	标准化、归一化、缺失值（一般使用pandas处理，sklearn中用SimpleImputer）

	缺失值处理的2种方式：
		删除：如果每列或者行数据缺失值达到一定的比例，建议放弃整行或者整列
		插补：可以通过缺失值每行或者每列的平均值、中位数来填充。
类别型数据：
	one-hot编码
时间类型：
	时间的切分（使用pandas处理）
"""

import numpy as np

#   特征预处理 数值型数据 标准缩放（标准化、归一化）
from sklearn import preprocessing


def minmax():
	"""
		归一化处理(缩放到指定范围)：
				归一化有同一、统一和合一的意思。
				归一化有可能将正常的样本“挤”到一起去。
				为了后面数据处理的方便，其次是保证程序运行时收敛加快。
				归一化的具体作用是归纳统一样本的统计分布性。
				特点：通过对原始数据进行变换把数据映射到(默认为[0,1])之间
				目的：使的某一个特征对最终结果不会造成更大影响。
				场景：如果数据较为稳定，不存在极端的最大最小值，用归一化。
	:return:
	"""
	mm = preprocessing.MinMaxScaler()  # 默认 （0,1）
	mm = preprocessing.MinMaxScaler(feature_range=(2, 3))
	arr = [[90, 2, 10, 40], [60, 4, 15, 45], [75, 3, 13, 46]]
	data = mm.fit_transform(arr)
	print('归一化处理:\n', data)
	print("---------------------------------------------------")
	print('归一化 inverse_transform :\n',mm.inverse_transform(data))
	print("---------------------------------------------------")
	return None


def stand():
	"""
	标准化缩放：标准化、归一化。

		标椎化、归一化，两种不同的缩放方式，目的都是缩小范围。
		标准化是将浮点数据缩放到 0 到 1 之间的值的过程。
		对于归一化来说,如果出现异常点，影响了最大值和最小值，那么结果显然会发生改变。
		对于标椎化来说，如果出现异常点，由于具有一定数据量，少量的异常点对于平局值的影响并不大，从而方差改变较小。


		场景：
			如果数据存在异常值和较多噪音，用标准化，可以间接通过中心化避免异常值和极端值的影响。
			在已有样本足够多的情况下比较稳定，适合现代嘈杂大数据场景。

	:return:
	"""
	std = preprocessing.StandardScaler()

	# fit_transform 一般是计算 平均值和标准差
	data = std.fit_transform([[1., -1., 3.], [2., 4., 2.], [4., 6., -1.]])

	print('标准化缩放:\n', data)

	print("---------------------------------------------------")
	print(std.mean_)

	return None


def im():
	"""
	缺失值处理
	:return:NOne
	"""
	# 'NaN', np.nan 都可以表示缺失值
	# im = preprocessing.Imputer(missing_values='NaN', strategy='mean', axis=0)
	# im = preprocessing.Imputer(missing_values=np.nan, strategy='mean', axis=0)

	from sklearn.impute import SimpleImputer
	im = SimpleImputer()  # 默认使用每列的 平均值 代替 缺失值
	data = im.fit_transform([[1, 2], [np.nan, 3], [7, 6]])

	print('缺失值处理:\n', data)

	return None


if __name__ == "__main__":
	# 归一化(缩放到指定范围)
	minmax()
	# 标准化缩放
	stand()
	# 缺失值处理
	im()
